/* debug.h
 *
 *    Copyright 2010 Patrick Allen
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
*/

#ifndef ADVRP_DEBUG_H
#define ADVRP_DEBUG_H

#include <inttypes.h>

/* XXX Ideas to make the debug facility more useful:
 *       - Possibility to have separate output streams per thread.
 *       \-> Instead of (or in addition to) passing a function name as an
 *           argument, pass the thread id/name.
 *
 *       - Debug flag to pause thread operation after outputting a message.
 *         Resume on a given event (like a keystroke).
 *
 *       - Add generic debug levels for INFO, WARN, etc.
 *      
 *      The above combined would let you use a GUI to display messages from
 *      each thread in their own separate sections, and let you step forward
 *      through each thread individually or simultaneously. Could be very
 *      useful when multiple things are happening at once and you don't want
 *      to miss anything.
 */

/* Debug levels */
#define ERR 0x0000000000000001LLU     // errors, should always be printed

/* Receiver debug -- increasing verbosity levels */
#define RECV_1 0x0000000000000010LLU  // Info -- short
#define RECV_2 0x0000000000000020LLU  // Info -- detailed
#define RECV_3 0x0000000000000040LLU  // Info -- very detailed
#define RECV_4 0x0000000000000080LLU  // Not used
#define RECV_5 0x0000000000000100LLU  // Not used
#define RECV_6 0x0000000000000200LLU  // Not used

/* Sender debug */
#define SEND_1 0x0000000000000800LLU  // As above
#define SEND_2 0x0000000000001000LLU
#define SEND_3 0x0000000000002000LLU
#define SEND_4 0x0000000000004000LLU
#define SEND_5 0x0000000000008000LLU
#define SEND_6 0x0000000000010000LLU

/* Verify debug */
#define VRFY_1 0x0000000000020000LLU  // As above
#define VRFY_2 0x0000000000040000LLU
#define VRFY_3 0x0000000000080000LLU
#define VRFY_4 0x0000000000100000LLU
#define VRFY_5 0x0000000000200000LLU
#define VRFY_6 0x0000000000400000LLU

/* Holddown debug */
#define HOLD_1 0x0000000000080000LLU  // As above
#define HOLD_2 0x0000000000100000LLU
#define HOLD_3 0x0000000000200000LLU
#define HOLD_4 0x0000000000400000LLU
#define HOLD_5 0x0000000000800000LLU
#define HOLD_6 0x0000000001000000LLU

/* Kernel debug */
#define KERN_1 0x0000000002000000LLU  // As above
#define KERN_2 0x0000000004000000LLU
#define KERN_3 0x0000000008000000LLU
#define KERN_4 0x0000000010000000LLU
#define KERN_5 0x0000000020800000LLU
#define KERN_6 0x0000000040000000LLU

/* Main debug */
#define MAIN_1 0x0000000100000000LLU  // As above
#define MAIN_2 0x0000000200000000LLU
#define MAIN_3 0x0000000400000000LLU
#define MAIN_4 0x0000000800000000LLU
#define MAIN_5 0x0000001000000000LLU
#define MAIN_6 0x0000002000000000LLU

/* Developer debug */
#define DEV_1       0x0000000000000002LLU   // Testing 1
#define DEV_2       0x0000000000000004LLU   // Testing 2
#define DEV_INOUT   0x0000000000000008LLU   // Entering and leaving functions

/* Output flags that may be toggled by users. */
#define TS_F       0x00000001   // Print timestamps
#define FN_F       0x00000002   // Print function names

/* Use DBG() instead of debug() to automatically add the calling function name 
 * as the first argument -- saves space.
 */
#define DBG(x ...); debug(__func__, x);

void debug(const char * fn, uint64_t level, char * buf, ...);

#endif
